home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
626-637
/
disk_635
/
ldp
/
source
/
ldp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
50KB
|
1,285 lines
/* Laser Disk Player program *\
** Copyright Ron M. Battle 1991 **
** HyperBorea Studio B **
** Manx Aztec C v5.2a **
** May be freely distributed for non-commercial use **
** *Revision History* **
**---------------------------------------------------**
** DATE VERSION COMMENTS **
**---------------------------------------------------**
** 02-22-92 1.31 Add SerialUnit **
** 02-15-92 1.3 Can run from WorkBench, **
** help key supported, **
** better error reporting, **
** ToolType defaults, **
** Thanx to Larry Shultz and **
** Brian Berg for LDP.info icons **
** 10-13-91 1.21 Dressed up remote with examples**
** from Brian Berg **
** 04-21-91 1.2 Generic Player revisions for **
** Hitachi, Pioneer, Sony **
** 09-29-90 1.1 Added ARexx interface **
** Thanx to GS & BH for FancyDemo**
** 02-25-90 1.0 Sony players only **
**---------------------------------------------------**
** The onscreen controller only uses a subset of **
** commands. This synchronous implementation is **
** not slick, could have better error checking, **
** but it WORKS!! **
** It would be nice to have more control over the **
** serial device's buffer. As it stands, the min **
** size is 512 bytes! This makes it more **
** difficult to keep track of lid openings,etc. **
** Since I'm synchronous, I don't check! **
** You could get around this by doing a continual **
** serial read with parameters for terminator char **
** and number of chars expected on the read. You **
** would need to modify the main event loop to also **
** wait for a message from mySerPort, but would be **
** better to set up a new message port for serial **
** reads! Use SendIO() for asynchronous reads, **
** when read done GetMsg(), get any errors from this**
** msg then SendIO() another read, etc.! **
** **
** REMOTE CONTROLLER COMMANDS: **
** **
** CL Clear commands **
** Index Toggle index display ON/OFF **
** <<< >>> Scan **
** << >> Fast **
** <| |> Slow **
** | < > | Step **
** < > Play **
** Search Search Hitachi&Sony: Srch Frame# Enter **
** Pioneer: Frame# Srch **
** Enter Enter For Hitachi&Sony players only **
** Log Log saves note and frame# in **
** ram:LDP.log **
** M+ Memorize current frame number **
** MR Search for memorized frame number **
** Still Still frame **
** Eject Eject disc **
** **
** You can also enter numbers into the display and **
** press return for a search. **
** If you don't do the commands in the proper **
** sequence, you might hang the controller. If you **
** don't like that.......CHANGE IT! **
** This controller also takes exclusive control **
** of the serial.device. Shared access never worked **
** properly! **
** **
\* */
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <workbench/icon.h>
#include <devices/serial.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <functions.h>
#include <rexx/storage.h>
#include "tinystring.h" /* The C routine index() causes contention */
#include "gadgets.h"
#include "video.h" /* this header would not pre-compile properly */
/* #define DEBUG 1 */
#define HELP 95 /* raw keycode for Help button */
/* defaults for serial device */
#define READ_BITS 8
#define WRITE_BITS 8
#define STOP_BITS 1
#define MIN_BAUD 1200
#define MAX_BAUD 9600
#define MIN_UNIT 0
#define MAX_UNIT 31
/* errors */
#define NO_ERR 0
#define READ_EXTIO_ERR 1
#define DEVICE_ERR 2
#define WRITEPORT_ERR 3
#define WRITE_EXTIO_ERR 4
#define INT_ERR 5 /* error opening intuition library */
#define WIN_ERR 6 /* error opening window */
#define REXX_ERR 7 /* error creating rexx port */
#define ILIB_ERR 8 /* error opening icon library */
char *ErrStr[] = {
"NONE!",
"Allocating read i/o block! ",
"Opening serial device! ",
"Creating write port! ",
"Allocating write i/o block! ",
"Opening Intuition library!",
"Opening window!",
"Creating rexx port!",
"Opening icon library!" };
#define MAXIN 6 /* size of in-buffers */
#define MAXOUT 22 /* size of out-buffer */
#define LDP_1000A 2 /* for SonyModel */
#define OTHER 1 /* means 180,1200,1500, or 2000 models */
#define ASLEEP 0 /* ldp not ready */
#define MAX_FRAME 54000 /* highest frame # */
#define MAX_FRAME_STR "54000" /* " " string */
#define D7 128 /* bit 7, used for masking */
#define D6 64
#define D5 32
#define D4 16
#define D3 8
#define D2 4
#define D1 2
#define D0 1
#define NOT_READY (D5 | D3 | D2) /* if any bits set: NOT READY */
#define REVERSE 0
#define FORWARD 1
#define ADD 1
#define NEW 0
#define DTEXT 0
#define DNUM 1
/* ARexx stuff */
#define HOST_PORT_NAME "LDP"
struct MsgPort *rexx_port = NULL ;
ULONG RexxSigMask ; /* signal mask used for WAIT() */
IMPORT struct Gadget EjectGad ; /* first gadget in list */
IMPORT struct Gadget NumDisplayGad, TextDisplayGad ;
IMPORT struct Gadget EnterGad ; /* will be disabled if pioneer player! */
IMPORT UBYTE NumBuff[NUMLEN], TextBuff[TEXTLEN] ;
struct MsgPort *mySerPort = NULL ;
struct IOExtSer *mySerReq = NULL ;
char ScratchBuff[MAXOUT] ;
char inbuff[MAXIN], outbuff[MAXOUT], StatusBuffer[MAXIN] ;
char *version = "$VER: LDP by HyperBorea Studio B V1.31__22.02.92(" ;
char *CmdTerm = NULL ; /* command terminator */
char *PlayerMode = NULL ; /* frame mode only for now */
char MemAddr[MAXIN] ; /* address for remote memorize */
char CurrentAddr[MAXIN] ; /* current address of player */
char *GadStr[] = { "","","","","","","","","","",
"Eject","Enter","Search","Still","Clear","Index","Rplay","Fplay",
"Rstep","Fstep","Rslow","Fslow",
"Rfast","Ffast","Rscan","Fscan",
"Memorize","Msearch","Log to ram:*","",""} ;
struct Window *wp=NULL ;
struct IntuitionBase *IntuitionBase=NULL ;
struct IconBase *IconBase=NULL ;
ULONG wakeupmask, UserSigMask ;
BOOL FscanDOWN = FALSE ;
BOOL RscanDOWN = FALSE ;
BOOL SearchPRESSED = FALSE ;
BOOL SerDeviceACTIVE = FALSE ;
BOOL LdpREADY = TRUE ;
BOOL IndexON = TRUE ;
BOOL ReversePolish = FALSE ; /* Pioneer players do arg,verb */
BOOL RemoteON = TRUE ; /* onscreen remote controller */
BOOL TimeToExit = FALSE ; /* used to exit ProcessEvents() */
USHORT CurrentCmd = 0 ; /* Current Command */
USHORT SonyModel = OTHER; /* default */
USHORT BaudRate = 1200 ; /* Fixed baud rate for SONY LDP-1000A */
USHORT PlayerType = sony ; /* default player */
USHORT ReturnBytes ; /* number of bytes returned from command */
USHORT AddrBytes ; /* number of bytes returned address query */
USHORT StatBytes ; /* number of bytes returned status query */
USHORT SerialUnit ; /* serial port unit number */
char HelpStr[] = {"\n\
Laser Disc Player by Ron M. Battle HyperBorea Studio B\n\
------------------------------------------------------------------------------\n\
CLI USAGE: run ldp -bBaud -pPlayerType -rRemoteOn/Off -uSerialUnit#\n\
example: run ldp -b1200 -pSony -rOn -u0 (DEFAULT)\n\
WB USAGE: ToolTypes: BAUD PLAYER REMOTE WINDOW UNIT\n\
example: BAUD=4800 PLAYER=PIONEER REMOTE=ON WINDOW=CON:20/20/320/70/LDP!\n\
Public Port: LDP (case sensitive)\n\
Note: On remote, click in text area, enter note and press LOG,\n\
current frame# and note will be saved to ram:LDP.log\n\
Help: Press Help key on keyboard!\n\
ARexx cmds:\n\
address (returns frame# as 32 bit integer) baud rate (set baud rate)\n\
clear (clear all commands) eject (open door) enter (terminate some commands)\n\
forward howfast (step/slow/fast/scan/normal) frame (set frame mode)\n\
index toggle (on/off) init (initialize player) play start end (play sequence)\n\
quit (shut down program) ready (returns 1 if player ready)\n\
reverse howfast (step/slow/fast/scan/normal) search frame# (ASCII digits)\n\
still (still frame)\n\
vplayer type (set player type: sony/hitachi/pioneer/none, returns 32 bit int)\n\n\
\n CLI ARexx example: rx 'address LDP play 5000 5100'\n\
------------------------------------------------------------------------------\n\n"};
struct NewWindow LdpWindow= {
10,10, /* window XY origin relative to TopLeft of screen */
200,162, /* window width and height */
0,3, /* detail and block pens */
GADGETDOWN+GADGETUP+CLOSEWINDOW+RAWKEY, /* IDCMP flags */
WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH+WINDOWSIZING,
&EjectGad, /* first gadget in gadget list */
NULL, /* custom CHECKMARK imagery */
(UBYTE *)"Sony LDP", /* window title */
NULL, /* custom screen pointer */
NULL, /* custom bitmap */
144,12, /* minimum width and height */
0,0, /* maximum width and height */
WBENCHSCREEN /* destination screen type */
};
void UpdateDisplay(char *dstring, int how, int which)
{
long gadpos ;
struct Gadget *gadptr ;
struct StringInfo *strgad ;
char *buffptr ;
if (which == DTEXT) {
gadptr = &TextDisplayGad ;
buffptr = (char *)TextBuff;
}
else {
gadptr = &NumDisplayGad ;
buffptr = (char *)NumBuff;
};
strgad=(struct StringInfo *)NumDisplayGad.SpecialInfo ;
gadpos = RemoveGadget(wp,gadptr) ; /* don't change before removing! */
if (how == ADD) { /* add to existing string */
if ((SHORT)strgad->NumChars < (NUMLEN-1)) {
strcat((char *)buffptr,dstring) ;
}
else strcpy((char *)buffptr,dstring) ; /* start over if too many! */
}
else {
strcpy((char *)buffptr,dstring) ; /* new string */
};
AddGadget(wp,gadptr,gadpos) ;
RefreshGList(gadptr,wp,NULL,gadpos) ;
}
void SetBaud(USHORT rate) /* set baud rate and 8N1 */
{
LONG error ;
if (rate>MAX_BAUD || rate<MIN_BAUD) rate=MIN_BAUD ; /* simple error checking */
mySerReq->io_Baud = rate ;
mySerReq->io_ReadLen = READ_BITS ;
mySerReq->io_WriteLen = WRITE_BITS ;
mySerReq->io_StopBits = STOP_BITS ;
mySerReq->IOSer.io_Command = SDCMD_SETPARAMS ;
if ((error = DoIO((struct IORequest *)mySerReq)) != 0L) {
printf("SetBaud error = %ld\n",error) ;
};
}
LONG ReadSer(char *data, USHORT length)
{
LONG error = 0L ;
USHORT i ;
for (i=0; i<MAXIN; inbuff[i]='\0',i++) ; /* clear out in buffer */
mySerReq->IOSer.io_Data = (APTR)data ;
mySerReq->IOSer.io_Length = (ULONG)length ;
mySerReq->IOSer.io_Command = CMD_READ ;
if ((error = DoIO((struct IORequest *)mySerReq)) != 0L) {
printf("ReadSer err# %ld\n",error) ;
};
#ifdef DEBUG
printf(" ReadHex= %X %X %X %X %X \n",
inbuff[0],inbuff[1],inbuff[2],inbuff[3],inbuff[4]) ;
#endif
return (error) ;
}
LONG WriteSer(char c)
{
LONG error ;
outbuff[0] = c ;
outbuff[1] = '\0'; /* null terminate just in case! */
#ifdef DEBUG
printf(" SendChar= %s\n",outbuff) ;
#endif
mySerReq->IOSer.io_Data = (APTR)outbuff ; /* change to once only!! */
mySerReq->IOSer.io_Length = 1L ;
mySerReq->IOSer.io_Command = CMD_WRITE ;
if ((error = DoIO((struct IORequest *)mySerReq)) != 0L) {
printf("WriteSer err# %ld\n",error);
};
return (error) ;
}
LONG SendString(char *buff)
{
LONG err,len ;
len = (long)strlen(buff) ;
#ifdef DEBUG
printf(" SendStr=%s\n",buff) ;
#endif
mySerReq->IOSer.io_Data = (APTR)buff ;
mySerReq->IOSer.io_Length = len ;
mySerReq->IOSer.io_Command = CMD_WRITE ;
if ((err = DoIO((struct IORequest *)mySerReq)) != 0L) {
printf("Write to serial port err# %ld\n",err);
};
return (err) ;
}
USHORT Ask_Sony_Model(UBYTE byt) /* returns LDP_1000A or OTHER or SLEEPING */
{
LONG err, count ;
USHORT model, status = FALSE ;
model = (byt & D7) ;
if (model == 0) model = LDP_1000A ;
status = !(byt & NOT_READY) ;
if (status == FALSE) model = ASLEEP ;
return(model) ;
}
void MyCleanup(USHORT err)
{
if (err) printf("LDP stopped because: ERROR %s\n",ErrStr[err]) ;
if ( (CheckIO(mySerReq)==FALSE)&&(err != WRITEPORT_ERR) ) {
AbortIO((struct IORequest *)mySerReq) ; /* abort any pending requests */
WaitIO((struct IORequest *)mySerReq) ;
};
if (SerDeviceACTIVE) CloseDevice((struct IORequest *)mySerReq) ;
if (wp != NULL) CloseWindow(wp) ;
if (IntuitionBase != NULL) CloseLibrary(IntuitionBase) ;
if (mySerReq != NULL) DeleteExtIO((struct IORequest *)mySerReq);
if (mySerPort != NULL) DeletePort(mySerPort) ;
if (rexx_port != NULL) DeletePort(rexx_port) ;
puts(" Please turn OFF the player when DONE!");
}
/* ARexx routines */
void SetupRexxPort(void)
{
struct MsgPort *the_port=NULL ;
Forbid() ;
if (FindPort(HOST_PORT_NAME)) {
Permit() ;
printf("A public port called '%s' already exists!\n",HOST_PORT_NAME) ;
the_port=NULL ;
}
the_port = CreatePort(HOST_PORT_NAME,0L) ;
Permit() ;
if (the_port != NULL) {
RexxSigMask = (1L<<the_port->mp_SigBit) ; /* setup signal bit */
rexx_port = the_port ;
}
else {
MyCleanup(REXX_ERR) ;
exit(FALSE) ;
}
}
void ReplyRexxMessage(struct RexxMsg *rexxmessage, long result)
{
rexxmessage->rm_Result1 = result ;
rexxmessage->rm_Result2 = 0L ;
ReplyMsg((struct Message *)rexxmessage) ;
}
void DoSimpleCmd(char *cmd)
{
strcpy(outbuff,cmd) ; /* now build output buffer */
strcat(outbuff,CmdTerm) ;
SendString(outbuff) ; /* send string to serial port */
ReadSer(inbuff,ReturnBytes); /* see what player returns */
}
void ClearSerialBuffer(void)
{
ULONG error ;
mySerReq->IOSer.io_Command = CMD_CLEAR; /* clear out device buffer */
if ((error = DoIO((struct IORequest *)mySerReq)) != 0L) {
printf("Clear serial buffer error# %ld\n",error);
}
}
long GetAddress(char *cmd) /* return player address as long int */
{
USHORT x,*intp ;
int y ;
long addr=0 ;
ClearSerialBuffer() ;
/* now build output buffer */
strcpy(outbuff,cmd) ; /* command */
strcat(outbuff,CmdTerm) ; /* command terminator, if any */
SendString(outbuff) ; /* send string to serial port */
ReadSer(inbuff,AddrBytes) ; /* see what player returns */
if(PlayerType == hitachi) {
intp = (USHORT *)(inbuff+1) ; /* skip past echo, hi-lo bytes follow */
addr = (long)*intp ; /* convert to long int */
y = sprintf(CurrentAddr,"%ld\0",addr); /* save addr as string */
}
else {
inbuff[5] = '\0' ; /* null terminate string */
strcpy(CurrentAddr,inbuff); /* save current address */
addr = atol(inbuff) ; /* convert string to signed long integer */
};
return(addr) ;
}
void SetIndex(char *toggle)
{
int offset = on ; /* default */
char *cmd ;
if (toggle != NULL) {
if(strncmp(toggle,indexstr[off],2L)==0) offset = off ;
}; /* now set a pointer to the correct index cmd */
cmd = Player[PlayerType].index[offset] ;
/* now build output buffer */
strcpy(outbuff,cmd) ;
strcat(outbuff,CmdTerm) ; /* add any cmd terminator */
SendString(outbuff) ; /* send string to serial port */
ReadSer(inbuff,ReturnBytes); /* see what player returns */
}
void Step1KA(int direction) /* Sony 1000A won't do single command stepping */
{ /* Actually the 2000 wouldn't either so all */
/* sonys now use this routine! */
/* has problems when stepping near frame 1-2 */
if (direction==FORWARD) { /* forward step */
WriteSer('='); /* send F-STEP */
ReadSer(inbuff,1) ; /* expect ACK */
WriteSer('O'); /* send STILL */
}
else { /* reverse step */
WriteSer('M'); /* send R-STEP */
ReadSer(inbuff,1);
WriteSer('O'); /* send STILL command, last ReadSer from Go() */
}
}
void Go(int direction, char *speed) /* tried to be generic except for Step-1KA */
{
int i=0,HowFast=0 ;
USHORT type=PlayerType,TotSpeeds=NUMSPEEDS-1 ;
/* now change string into an index */
while ((i < TotSpeeds) && (strncmp(speed,speedstr[i],3L) !=0)) i++ ;
HowFast = i ; /* if no match, defaults to normal */
if (direction==FORWARD) strcpy(outbuff,Player[type].forward[HowFast]);
else strcpy(outbuff,Player[type].reverse[HowFast]);
strcat(outbuff,CmdTerm) ; /* add any terminator */
if ((type==sony)&&(HowFast==step)) Step1KA(direction);
else SendString(outbuff) ;
ReadSer(inbuff,ReturnBytes) ;
}
void GoSearch(char *addr)
{
char *cmd,*temp,*fmode,*entercmd ;
long num ;
num = atol(addr) ;
if (num<1) addr="1" ; /* error checking */
if (num>54000) addr="54000" ;
cmd = Player[PlayerType].generic[search] ; /* get the search cmd */
fmode = PlayerMode ; /* get current mode cmd */
entercmd = Player[PlayerType].generic[enter]; /* get enter cmd */
if (ReversePolish == TRUE) { /* pioneer players are like this */
strcpy(outbuff,fmode) ; /* frame mode first */
strcat(outbuff,addr) ; /* put address in second */
strcat(outbuff,cmd) ; /* now add the command */
strcat(outbuff,CmdTerm); /* add any terminator */
SendString(outbuff) ; /* send the whole thing */
ReadSer(inbuff,ReturnBytes); /* expect R and CR */
}
else {
if (PlayerType == sony) { /* sony players */
strcpy(ScratchBuff,fmode); /* frame mode first */
strcat(ScratchBuff,cmd) ; /* put command in next */
strcat(ScratchBuff,addr) ; /* now add the address */
strcat(ScratchBuff,entercmd); /* add the enter cmd */
strcat(ScratchBuff,CmdTerm) ;/* add terminator */
for(temp=ScratchBuff; *temp!='\0'; temp++) {
WriteSer(*temp) ; /* send single char */
ReadSer(inbuff,ReturnBytes); /* expect ACK each time */
};
ReadSer(inbuff,1) ; /* expect completion code */
} /* end if sony */
else { /* hitachi players */
strcpy(outbuff,cmd) ; /* put command in first */
strcat(outbuff,fmode) ; /* frame mode next */
strcat(outbuff,cmd) ; /* put command in next */
strcat(outbuff,addr) ; /* now add the address */
strcat(outbuff,entercmd); /* add the enter cmd */
SendString(outbuff) ; /* send the whole thing */
ReadSer(inbuff,2) ; /* expect enter and job done */
} /* else hitachi */
} /* else reverse polish */
} /* proc */
BOOL CheckReady(void)
{
char *cmd ;
BOOL ok=TRUE,myIO ;
ClearSerialBuffer() ; /* make sure no garbage left over in buffer */
cmd = Player[PlayerType].generic[ready] ;
/* now build output buffer */
strcpy(outbuff,cmd) ; /* command */
strcat(outbuff,CmdTerm) ; /* cmd terminator, if any */
SendString(outbuff) ; /* send string to serial port */
mySerReq->IOSer.io_Data = (APTR)inbuff ;
mySerReq->IOSer.io_Length = (ULONG)StatBytes ;
mySerReq->IOSer.io_Command = CMD_READ ;
SendIO((struct IORequest *)mySerReq) ; /* asynchronous */
Delay(4L) ; /* 4/60 sec delay */
myIO = CheckIO((struct IORequest *)mySerReq) ; /* see if done */
if (myIO == FALSE) {
Delay(600L) ; /* wait about 10 more seconds */
myIO = CheckIO((struct IORequest *)mySerReq) ;
if (myIO == FALSE) {
AbortIO((struct IORequest *)mySerReq) ;
SonyModel = ASLEEP ;
return(FALSE) ;
}
} ;
GetMsg(mySerPort) ; /* recycle message */
switch (PlayerType) {
case sony : /* Bit7 is zero for LDP-1000A */
#ifdef DEBUG
printf(" StatusIn= %d\n",*inbuff) ;
#endif
SonyModel = Ask_Sony_Model(inbuff[0]) ;
if (SonyModel == ASLEEP) ok = FALSE ;
break ;
case hitachi : ok = TRUE ; /* no ready status available! */
break ;
case pioneer : /* buffer contents might be P01,P02,P06,etc. */
#ifdef DEBUG
printf(" StatusIn= %s\n",inbuff) ;
#endif
/* if (inbuff[2] < '4') ok = FALSE ; */
ok = TRUE ; /* Don't look at what is returned! */
break ;
default : break ;
} ;
return (ok) ;
}
void InitPlayer(void)
{
char *temp, *MyInit ;
if (PlayerType != none) {
SetBaud(BaudRate) ;
ReversePolish = Player[PlayerType].rp ; /* as in PIONEER! */
CmdTerm = Player[PlayerType].term ; /* set up command terminator */
PlayerMode = Player[PlayerType].generic[frame]; /* frame mode default */
ReturnBytes = Player[PlayerType].returnbytes; /* command return bytes */
StatBytes = Player[PlayerType].statbytes; /* # status bytes returned */
AddrBytes = Player[PlayerType].addrbytes; /* # address '' '' */
MyInit = Player[PlayerType].generic[init] ;
if (PlayerType==hitachi) DoSimpleCmd(MyInit) ;
LdpREADY = CheckReady() ;
if (LdpREADY) {
if (PlayerType != sony) Go(FORWARD,"normal") ; /* spin it up */
if (PlayerType == pioneer) DoSimpleCmd(MyInit);
if (PlayerType == sony) { /* can't send whole string at once */
for (temp=MyInit; *temp != '\0'; temp++) {
WriteSer(*temp) ; /* send single char */
ReadSer(inbuff,ReturnBytes); /* expect ACK each time */
}
}
SetIndex("on") ; /* set on-screen display */
GoSearch("1") ; /* now go to first frame */
}
}
else LdpREADY = FALSE ;
}
void PlaySequence(char *start,char *end) /* I got tired of being GENERIC! */
{ /* The following is BRUTE FORCE! */
char *temp,*entercmd,*searchcmd,*repeatcmd,*playcmd,*mem1 ;
USHORT x ;
long startnum,endnum ;
entercmd = Player[PlayerType].generic[enter] ;
searchcmd = Player[PlayerType].generic[search] ;
repeatcmd = Player[PlayerType].generic[repeat] ;
mem1 = Player[PlayerType].special1 ; /* hitachi */
startnum = atol(start) ;
endnum = atol(end) ;
if (startnum<1) start="1" ; /* error checking */
if (startnum>54000) start="27000" ;
if (endnum<1) end ="1" ;
if (endnum>54000) end="27000" ;
startnum = atol(start) ;
endnum = atol(end) ;
switch (PlayerType) {
case sony :
SendString(PlayerMode) ;
ReadSer(inbuff,1) ;
SendString(searchcmd) ;
ReadSer(inbuff,1) ;
for(temp=start; *temp!='\0'; temp++) {
WriteSer(*temp) ; /* send single char */
ReadSer(inbuff,1); /* expect ACK each time */
};
SendString(entercmd) ;
ReadSer(inbuff,1) ;
ReadSer(inbuff,1) ; /* expect completion code */
SendString(repeatcmd) ;
ReadSer(inbuff,1) ;
for(temp=end; *temp!='\0'; temp++) {
WriteSer(*temp) ; /* send single char */
ReadSer(inbuff,1); /* expect ACK each time */
};
SendString(entercmd) ;
ReadSer(inbuff,1) ;
SendString("1") ;
ReadSer(inbuff,1) ;
SendString(entercmd) ;
ReadSer(inbuff,1) ;
ReadSer(inbuff,1) ; /* get completion code */
break ;
case pioneer : /* ok to send up to 20 char in one command, CR terminated */
if (startnum < endnum) playcmd = Player[pioneer].forward[normal] ;
else playcmd = Player[pioneer].reverse[normal] ;
strcpy(outbuff,PlayerMode) ; /* frame mode */
strcat(outbuff,start) ; /* put search address */
strcat(outbuff,searchcmd); /* put SEarch command */
strcat(outbuff,CmdTerm) ; /* CR terminator */
SendString(outbuff);
ReadSer(inbuff,ReturnBytes);
strcpy(outbuff,end); /* put play to address */
strcat(outbuff,"SM"); /* Stop Marker */
strcat(outbuff,playcmd) ; /* put multi-speed command */
strcat(outbuff,CmdTerm) ; /* terminate command (CR) */
SendString(outbuff) ; /* send commands to player */
ReadSer(inbuff,ReturnBytes); /* expect back R and CR */
break ;
case hitachi : /* ok to send as a string */
strcpy(outbuff,searchcmd) ; /* search command first */
strcat(outbuff,PlayerMode); /* frame command next */
strcat(outbuff,start) ; /* now start address */
strcat(outbuff,mem1) ; /* remember this location */
strcat(outbuff,end) ; /* now end address */
strcat(outbuff,entercmd) ; /* terminate with enter */
SendString(outbuff) ; /* send it out */
ReadSer(inbuff,2) ; /* expect ENTER & JOB END */
break ; /* JOB END = SEARCH+80H */
default :
break ;
} /* switch */
} /* proc */
long DoCommand(char *cmd, char *arg1, char *arg2)
{
int c=0,i ;
long result= 0 ;
char *current= NULL ; /* pointer to current command */
/* now check only the 1st 3 letters of command and increment cmd index */
while ((c < NUMCMDS) && (strncmp(cmd, VideoCmd[c],3) != 0)) c++ ;
CurrentCmd = c ; /* global variable, use to index into generic commands */
current = Player[PlayerType].generic[CurrentCmd];
switch (c) {
case address : if (LdpREADY) {
result = GetAddress(current) ;
};
break ;
case baud : /* set baud rate of AMIGA serial port */
/* laser player should MATCH rate! */
/* usual rates are 1200,4800,9600 */
if (arg1 != NULL) {
BaudRate = (USHORT)atoi(arg1); /* convert str->int */
SetBaud(BaudRate) ;
} ;
result = (long)BaudRate ; /* return long integer */
break ;
case clear : if (LdpREADY) {
ClearSerialBuffer() ;
DoSimpleCmd(current) ;
};
break ;
case eject : if (LdpREADY) DoSimpleCmd(current) ;
break ;
case enter : if (LdpREADY) DoSimpleCmd(current) ;
break ;
case forward : if (LdpREADY) Go(FORWARD,arg1) ;
break ;
case frame : if (LdpREADY) DoSimpleCmd(current) ;
break ;
case index : if (LdpREADY) SetIndex(arg1) ;
break ;
case init : InitPlayer() ;
result = (long)LdpREADY ;
break ;
case play : if (LdpREADY) PlaySequence(arg1,arg2) ;
break ;
case quit : TimeToExit = TRUE ; /* shutdown the program */
break ; /* useful if no remote! */
case ready : result = (long)CheckReady() ;
break ;
case reverse : if (LdpREADY) Go(REVERSE,arg1) ;
break ;
case search : if (LdpREADY) GoSearch(arg1) ;
break ;
case still : if (LdpREADY) DoSimpleCmd(current) ;
break ;
case vplayer : /* select video player type */
/* echo back or return current player if no arg1 */
if(arg1 != NULL) {
result = (long)(*arg1); /* echo char if not illegal */
switch(*arg1) { /* *arg1 is 1st char of string! */
case 's' : PlayerType = sony ;
InitPlayer() ;
break ;
case 'p' : PlayerType = pioneer ;
InitPlayer() ;
break ;
case 'h' : PlayerType = hitachi ;
InitPlayer() ;
break ;
case 'n' : PlayerType = none ;
LdpREADY = FALSE ;
break ;
default : result = (long)*PlayerStr[PlayerType] ;
break ; /* return current if illegal */
} /* switch */
} /* if */
else result = (long)*PlayerStr[PlayerType] ;
if(wp!=NULL)SetWindowTitles(wp,PlayerStr[PlayerType],NULL);
break ;
default : puts("ILLEGAL command!!") ;
result = 255L ;
break ;
};
return(result) ;
}
void execute_command(struct RexxMsg *rexxmessage)
{
char *token[4], *temp ; /* token[0]=Command, others=arguments */
int err ; /* this routine crashes system if total */
USHORT x ; /* tokens not 1 greater! */
long result=0 ; /* eg: cmd arg1 arg2 tokens=3+1 */
for (x=0; x<4; token[x]=NULL,x++) ; /* clear out token buffer */
token[0] = (char *)rexxmessage->rm_Args[0] ; /* parse ARexx string, */
token[0] = strtok(token[0],(char *)" ,") ; /* look for space or , */
for (x=1; (token[x] = strtok(NULL,(char *)" ,")) != NULL; x++) ;
for (x=0; x<4; x++) { /* convert all strings to lower-case */
strlwr(token[x]) ;
} ;
result = DoCommand(token[0],token[1],token[2]) ;
ReplyRexxMessage(rexxmessage,result) ;
}
/* Process Gadgets */
void ProcessGadgetUp(USHORT mygad)
{
char *addrcmd=Player[PlayerType].generic[address] ;
char ThisChar[2], *num, PriorStr[TEXTLEN] ;
LONG temp ;
FILE *NoteFile ;
switch (mygad) {
case Memorize : strcpy(PriorStr,(char *)TextBuff); /* save prior info */
UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
temp=GetAddress(addrcmd) ;
addrcmd=strcpy(MemAddr,CurrentAddr); /* save MemAddr */
UpdateDisplay(MemAddr,NEW,DNUM) ;
Delay(30L) ;
UpdateDisplay(PriorStr,NEW,DTEXT) ;
break ;
case Msearch : UpdateDisplay(MemAddr,NEW,DNUM) ;
UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
GoSearch(MemAddr) ;
break ;
case Log : strcpy(PriorStr,(char *)TextBuff) ; /* save note */
UpdateDisplay(GadStr[mygad],NEW,DTEXT) ; /* logging */
temp=GetAddress(addrcmd) ; /* show current address */
UpdateDisplay(CurrentAddr,NEW,DNUM) ;
NoteFile = fopen("ram:LDP.log","a") ; /* save to file */
fprintf(NoteFile,"%s %s\n",CurrentAddr,PriorStr) ;
fclose(NoteFile) ;
Delay(30L) ;
UpdateDisplay(PriorStr,NEW,DTEXT) ; /* reshow note */
break ;
case Index : IndexON ^= TRUE ; /* toggle on/off */
if (IndexON) SetIndex("on");
else SetIndex("off");
break ;
case NumDisplay : if (PlayerType == pioneer) {
UpdateDisplay("Search",NEW,DTEXT) ;
SearchPRESSED = TRUE ;
GoSearch((char *)NumBuff) ;
}
else {
if (SearchPRESSED) {
SearchPRESSED = FALSE ;
UpdateDisplay(GadStr[Enter],NEW,DTEXT) ;
if (PlayerType == hitachi) {
SendString((char *)NumBuff) ;
}
else { /* sony players */
for (num=(char *)NumBuff; *num !='\0'; num++) {
WriteSer(*num) ;
ReadSer(inbuff,1) ;
}
};
SendString(Player[PlayerType].generic[enter]);
/* expect back ACK,COMPLETION or ECHO,JOB DONE */
ReadSer(inbuff,2) ;
}
else {
UpdateDisplay("Search/Enter",NEW,DTEXT) ;
GoSearch((char *)NumBuff) ;
}
};
break ;
case Search : if ((SearchPRESSED==TRUE) && (PlayerType!=pioneer)) {
UpdateDisplay("ERROR!",NEW,DTEXT) ;
break ;
};
UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
SearchPRESSED = TRUE ;
if (PlayerType != pioneer) UpdateDisplay("",NEW,DNUM);
else SendString((char *)NumBuff);
DoSimpleCmd(Player[PlayerType].generic[search]);
if (PlayerType == hitachi) {
DoSimpleCmd(Player[hitachi].generic[frame]) ;
};
break ;
case Still : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
DoSimpleCmd(Player[PlayerType].generic[still]) ;
Delay(1L) ;
temp=GetAddress(addrcmd) ; /* show current address */
UpdateDisplay(CurrentAddr,NEW,DNUM) ;
break ;
case Clear : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
UpdateDisplay("",NEW,DNUM) ;
ClearSerialBuffer() ;
DoSimpleCmd(Player[PlayerType].generic[clear]) ;
SearchPRESSED = FALSE ;
break ;
case Enter : UpdateDisplay(GadStr[mygad],NEW,DTEXT);
if (SearchPRESSED) { /* send buff next */
SearchPRESSED = FALSE ;
if (PlayerType == hitachi) {
SendString((char *)NumBuff) ;
}
else { /* for sony: send single chars */
for (num=(char *)NumBuff; *num !='\0'; num++) {
WriteSer(*num) ;
ReadSer(inbuff,1) ;
}
};
SendString(Player[PlayerType].generic[enter]);
/* expect back ACK,COMPLETION or ECHO,JOB DONE */
ReadSer(inbuff,2) ;
}
else UpdateDisplay("ERROR!",NEW,DTEXT) ;
break ;
case Eject : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
DoSimpleCmd(Player[PlayerType].generic[eject]) ;
break ;
case Fplay : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(FORWARD,"normal") ;
break ;
case Rplay : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(REVERSE,"normal") ;
break ;
case Fslow : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(FORWARD,"slow") ;
break ;
case Rslow : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(REVERSE,"slow") ;
break ;
case Ffast : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(FORWARD,"fast") ;
break ;
case Rfast : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(REVERSE,"fast") ;
break ;
case Fscan : FscanDOWN = FALSE ; /* scan button UP is still frame */
DoSimpleCmd(Player[PlayerType].generic[still]) ;
Delay(4L) ;
temp=GetAddress(addrcmd) ; /* show current address */
UpdateDisplay(CurrentAddr,NEW,DNUM) ;
break ;
case Rscan : RscanDOWN = FALSE ;
DoSimpleCmd(Player[PlayerType].generic[still]) ;
Delay(4L) ;
temp=GetAddress(addrcmd) ; /* show current address */
UpdateDisplay(CurrentAddr,NEW,DNUM) ;
break ;
case Fstep : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(FORWARD,"step");
Delay(1L) ;
temp=GetAddress(addrcmd) ; /* show current address */
UpdateDisplay(CurrentAddr,NEW,DNUM) ;
break ;
case Rstep : UpdateDisplay(GadStr[mygad],NEW,DTEXT) ;
Go(REVERSE,"step");
Delay(1L) ;
temp=GetAddress(addrcmd) ; /* show current address */
UpdateDisplay(CurrentAddr,NEW,DNUM) ;
break ;
case Zero: case One: case Two: case Three: case Four:
ThisChar[0] = (mygad+48) ;
ThisChar[1] = '\0' ;
UpdateDisplay(ThisChar,ADD,DNUM) ; /* accumulate chars in NumBuff */
break ;
case Five: case Six: case Seven: case Eight: case Nine:
ThisChar[0] = (mygad+48) ;
ThisChar[1] = '\0' ;
UpdateDisplay(ThisChar,ADD,DNUM) ;
break ;
default : break ;
} /* switch */
} /* proc */
void ProcessGadgetDown(USHORT mygad)
{
switch (mygad) {
case Fscan : UpdateDisplay("Fscan ",NEW,DTEXT) ;
FscanDOWN = TRUE ;
Go(FORWARD,"scan") ;
break ;
case Rscan : UpdateDisplay("Rscan ",NEW,DTEXT) ;
RscanDOWN = TRUE ;
Go(REVERSE,"scan") ;
break ;
default : break ;
} /* switch */
} /* proc */
void ProcessEvents(void)
{
struct IntuiMessage *eventptr ;
struct RexxMsg *rexxmessage ;
ULONG class ;
USHORT code, mygad ;
struct Gadget *GadPtr ;
SHORT y ;
while (!TimeToExit) {
wakeupmask = Wait(UserSigMask | RexxSigMask) ; /* now wait for events... */
if (wakeupmask & RexxSigMask) { /* process Rexx commands */
while ( (rexxmessage = (struct RexxMsg *)GetMsg(rexx_port)) ) {
execute_command(rexxmessage) ;
}
} ;
if (wakeupmask & UserSigMask) { /* process remote controller commands */
while ( (eventptr = (struct IntuiMessage *)GetMsg(wp->UserPort)) ) {
class = eventptr->Class ;
code = eventptr->Code ; /* Save values of interest */
GadPtr = (struct Gadget *)eventptr->IAddress ;
y = eventptr->MouseY ;
ReplyMsg( (struct Message *) eventptr ) ; /* Reply QUICKLY! */
mygad = GadPtr->GadgetID ;
switch (class) {
case GADGETUP : if (LdpREADY) {
ProcessGadgetUp(mygad) ;
};
break ;
case GADGETDOWN : if (LdpREADY) {
ProcessGadgetDown(mygad) ;
};
break ;
case CLOSEWINDOW : TimeToExit = TRUE ;
break ;
case RAWKEY : if (code == HELP) printf("%s",HelpStr) ;
break ;
default : break ;
} /* switch */
} /* while */
} /* if UserSigMask */
} ; /* while timetoexit */
while ( (eventptr = (struct IntuiMessage *)GetMsg(wp->UserPort)) ) {
ReplyMsg( (struct Message *) eventptr ) ; /* clear out intuition messages */
};
while ( (rexxmessage = (struct RexxMsg *)GetMsg(rexx_port)) ) {
ReplyMsg( (struct Message *) rexxmessage) ; /* clear out arexx messages */
}
} /* proc */
void SetupPorts(void)
{ LONG i, error,unit=(long)SerialUnit ;
BYTE *b, *c ;
mySerPort = CreatePort("mySerialPort",0L) ;
if (mySerPort == NULL) {
MyCleanup(WRITEPORT_ERR) ;
exit(FALSE) ;
};
i = (LONG)sizeof(struct IOExtSer) ;
mySerReq = (struct IOExtSer *)CreateExtIO(mySerPort,i) ;
if (mySerReq == NULL) {
MyCleanup(READ_EXTIO_ERR) ;
exit(FALSE) ;
} ;
mySerReq->io_SerFlags = (SERF_RAD_BOOGIE | SERF_7WIRE); /* FAST I/O! */
error = OpenDevice("serial.device",unit,(struct IORequest *)mySerReq,0L) ;
if (error != 0) {
MyCleanup(DEVICE_ERR) ;
exit(FALSE) ;
}
else SerDeviceACTIVE = TRUE ;
}
void OpenLibs(void)
{
IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0L);
if (IntuitionBase == NULL) {
MyCleanup(INT_ERR) ;
exit(FALSE) ;
}
}
void InitWindow(void)
{
LdpWindow.Title = (UBYTE *)PlayerStr[PlayerType] ;
if (SonyModel == LDP_1000A) LdpWindow.Title = (UBYTE *)"SONY-1KA" ;
if (LdpREADY == FALSE) {
strcpy(ScratchBuff,(char *)LdpWindow.Title) ;
strcat(ScratchBuff," ASLEEP!") ;
LdpWindow.Title = (UBYTE *)ScratchBuff ;
} ;
if ((wp = OpenWindow(&LdpWindow)) == NULL) {
MyCleanup(WIN_ERR) ;
exit(FALSE) ;
} ;
if (PlayerType == pioneer) OffGadget(&EnterGad,wp,NULL); /* disable Enter */
if (LdpREADY != TRUE) UpdateDisplay("RESTART!",NEW,DTEXT) ;
UserSigMask = (1L << wp->UserPort->mp_SigBit) ; /* set up signal for events */
}
void SetPlayer(char *type)
{
switch (*type) { /* look at first character */
case 's' : PlayerType = sony ;
break ;
case 'p' : PlayerType = pioneer ;
break ;
case 'h' : PlayerType = hitachi ;
break ;
case 'n' : PlayerType = none ;
break ;
default : PlayerType = sony ; /* default player is sony */
break ;
} /* switch */
}
void ParseCmdLine(char *arg[]) /* global variables will be modified */
{
USHORT i ;
char *temp,*baud,*remote,*player,*unit ;
if (strcmp(arg[1],"?")==0) { /* give help */
printf("%s",HelpStr) ;
arg[1]="-pnone" ;
};
for (i=0; arg[i] != NULL ; i++) { /* convert to lower-case first */
for (temp = arg[i]; *(temp) != '\0'; temp++) *temp=tolower(*temp) ;
if ((baud = strchr(arg[i],'b'))!= NULL) { /* look for baud rate */
baud++ ; /* increment pointer past 'b' */
BaudRate = (USHORT)atoi(baud) ; /* convert string to integer value */
} ;
if ((player = strchr(arg[i],'p'))!= NULL) { /* look for player name */
player++ ; /* increment pointer past 'p' */
SetPlayer(player) ;
}; /* if */
if ((remote = strchr(arg[i],'r'))!= NULL) { /* look for remote toggle*/
remote++ ; /* increment pointer past 'r' */
if (strncmp(remote,indexstr[off],2L)==0) RemoteON = FALSE ;
};
if ((unit = strchr(arg[i],'u'))!= NULL) { /* look for serial unit# */
unit++ ; /* increment pointer past 'u' */
SerialUnit = (USHORT)atoi(unit) ; /* convert str to integer */
if (SerialUnit < MIN_UNIT || SerialUnit > MAX_UNIT) SerialUnit = MIN_UNIT ;
} /* if */
} /* for loop */
} /* proc */
void GetTooltypes(struct WBStartup *msg)
{
struct WBArg *arg ;
struct DiskObject *diskobj ;
char **toolarray ; /* pointer to an array of string pointers */
char *value ;
if ((IconBase = OpenLibrary(ICONNAME,1L)) == NULL) {
MyCleanup(ILIB_ERR) ;
exit(FALSE) ;
};
arg=msg->sm_ArgList; /* get argument list from WB startup msg */
diskobj = GetDiskObject(arg->wa_Name) ; /* now get info from icon */
toolarray = diskobj->do_ToolTypes ; /* setup ToolType array */
value = FindToolType(toolarray,"PLAYER") ;
strlwr(value) ; /* convert to lower case */
SetPlayer(value) ; /* setup player type */
value = FindToolType(toolarray,"BAUD") ;
BaudRate = (USHORT)atoi(value) ; /* setup baud rate */
if (BaudRate == 0) BaudRate = MIN_BAUD ;
value = FindToolType(toolarray,"REMOTE") ;
if (stricmp(value,"OFF")==0) RemoteON = FALSE ; /* setup onscreen display */
else RemoteON = TRUE ;
value = FindToolType(toolarray,"UNIT") ;
SerialUnit = (USHORT)atoi(value) ; /* setup serial unit# */
if (SerialUnit < MIN_UNIT || SerialUnit > MAX_UNIT) SerialUnit = MIN_UNIT ;
FreeDiskObject(diskobj); /* cleanup */
CloseLibrary(IconBase) ;
}
/* ******* MAIN PROGRAM ****** */
main(int argc, char *argv[])
{
puts("") ;
if (argc > 1) ParseCmdLine(argv) ; /* cmd line startup */
else if (argc == 0) GetTooltypes((struct WBStartup *)argv) ; /* WB startup */
puts(" Default is SONY 1200Baud RemoteON") ;
OpenLibs() ;
SetupPorts() ;
ClearSerialBuffer() ;
SetupRexxPort() ;
puts(" Waiting......") ;
InitPlayer() ;
if (RemoteON) InitWindow() ; /* show controller on screen */
if (!LdpREADY) puts(" Need to RESTART!") ;
else puts(" Player READY!") ;
ProcessEvents() ; /* Main loop */
MyCleanup(NO_ERR) ;
}